package com.xing.binbackend.http.webclient;

import com.xing.binbackend.http.HttpClientStrategy;
import com.xing.binbackend.http.RestfulParameters;
import com.xing.binbackend.http.RestfulResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

@Component
public class WebClientStrategy implements HttpClientStrategy {
    private final WebClient webClient;

    public WebClientStrategy() {
        this.webClient = WebClient.create();
    }

    public <T> RestfulResponse<T> getSync(String url, RestfulParameters params,
                                          Class<T> responseType) {
        return webClient.get().uri(uriBuilder -> {
            uriBuilder.path(url);
            params.getParamMap().forEach(uriBuilder::queryParam);
            return uriBuilder.build();
        }).headers(headers -> params.getHeaderMap().forEach(headers::add)).retrieve().bodyToMono(responseType).map(data -> new RestfulResponse<>(200, "Success", data)).onErrorResume(e -> Mono.just(new RestfulResponse<>(500, e.getMessage(), null))).block(); // 阻塞直到获取响应
    }

    // 异步 GET 请求
    public <T> CompletableFuture<RestfulResponse<T>> getAsync(String url,
                                                              RestfulParameters params,
                                                              Class<T> responseType) {
        return webClient.get().uri(uriBuilder -> {
            uriBuilder.path(url);
            params.getParamMap().forEach(uriBuilder::queryParam);
            return uriBuilder.build();
        }).headers(headers -> params.getHeaderMap().forEach(headers::add)).retrieve().bodyToMono(responseType).map(data -> new RestfulResponse<>(200, "Success", data)).onErrorResume(e -> Mono.just(new RestfulResponse<>(500, e.getMessage(), null))).toFuture(); // 返回 CompletableFuture
    }

    @Override
    public <T> RestfulResponse<T> get(String url, RestfulParameters params, Class<T> responseType) {
        return webClient.get().uri(uriBuilder -> {
            uriBuilder.path(url);
            params.getParamMap().forEach(uriBuilder::queryParam);
            return uriBuilder.build();
        }).headers(headers -> params.getHeaderMap().forEach(headers::add)).retrieve().bodyToMono(responseType).map(data -> new RestfulResponse<>(200, "Success", data)).onErrorResume(e -> Mono.just(new RestfulResponse<>(500, e.getMessage(), null))).block();
    }


    @Override
    public <T> RestfulResponse<T> post(String url, RestfulParameters params,
                                       Class<T> responseType) {
        return webClient.post().uri(uriBuilder -> {
                    uriBuilder.path(url);
                    params.getParamMap().forEach(uriBuilder::queryParam); // 将查询参数添加到 URL
                    return uriBuilder.build();
                }).headers(headers -> params.getHeaderMap().forEach(headers::add)) // 设置请求头
                .bodyValue(params.getBody()) // 设置请求体
                .retrieve().bodyToMono(responseType).map(data -> new RestfulResponse<>(200,
                        "Success", data)).onErrorResume(e -> Mono.just(new RestfulResponse<>(500,
                        e.getMessage(), null))).block();
    }

    public <T> RestfulResponse<T> postSync(String url, RestfulParameters params,
                                           Class<T> responseType) {
        return webClient.post().uri(uriBuilder -> {
            uriBuilder.path(url);
            params.getParamMap().forEach(uriBuilder::queryParam);
            return uriBuilder.build();
        }).headers(headers -> params.getHeaderMap().forEach(headers::add)).bodyValue(params.getBody()).retrieve().bodyToMono(responseType).map(data -> new RestfulResponse<>(200, "Success", data)).onErrorResume(e -> Mono.just(new RestfulResponse<>(500, e.getMessage(), null))).block(); // 阻塞直到获取响应
    }

    // 异步 POST 请求
    public <T> CompletableFuture<RestfulResponse<T>> postAsync(String url,
                                                               RestfulParameters params,
                                                               Class<T> responseType) {
        return webClient.post().uri(uriBuilder -> {
            uriBuilder.path(url);
            params.getParamMap().forEach(uriBuilder::queryParam);
            return uriBuilder.build();
        }).headers(headers -> params.getHeaderMap().forEach(headers::add)).bodyValue(params.getBody()).retrieve().bodyToMono(responseType).map(data -> new RestfulResponse<>(200, "Success", data)).onErrorResume(e -> Mono.just(new RestfulResponse<>(500, e.getMessage(), null))).toFuture(); // 返回 CompletableFuture
    }

    @Override
    public <T> RestfulResponse<T> put(String url, RestfulParameters params, Class<T> responseType) {
        return webClient.put().uri(uriBuilder -> {
            uriBuilder.path(url);
            params.getParamMap().forEach(uriBuilder::queryParam);
            return uriBuilder.build();
        }).headers(headers -> params.getHeaderMap().forEach(headers::add)).bodyValue(params.getBody()).retrieve().bodyToMono(responseType).map(data -> new RestfulResponse<>(200, "Success", data)).onErrorResume(e -> Mono.just(new RestfulResponse<>(500, e.getMessage(), null))).block();
    }

    @Override
    public <T> RestfulResponse<T> delete(String url, RestfulParameters params,
                                         Class<T> responseType) {
        return webClient.delete().uri(uriBuilder -> {
            uriBuilder.path(url);
            params.getParamMap().forEach(uriBuilder::queryParam);
            return uriBuilder.build();
        }).headers(headers -> params.getHeaderMap().forEach(headers::add)).retrieve().bodyToMono(responseType).map(data -> new RestfulResponse<>(200, "Success", data)).onErrorResume(e -> Mono.just(new RestfulResponse<>(500, e.getMessage(), null))).block();
    }


    // 构建完整的 URL
    private String buildFullUrl(String url, Map<String, String> queryParams) {
        StringBuilder fullUrl = new StringBuilder(url);
        if (!queryParams.isEmpty()) {
            fullUrl.append("?");
            queryParams.forEach((key, value) -> fullUrl.append(key).append("=").append(value).append("&"));
            fullUrl.deleteCharAt(fullUrl.length() - 1); // 删除最后一个 "&"
        }
        return fullUrl.toString();
    }

    // 将 Map<String, String> 转换为 MultiValueMap<String, String>
    private MultiValueMap<String, String> convertToMultiValueMap(Map<String, String> map) {
        MultiValueMap<String, String> multiValueMap = new LinkedMultiValueMap<>();
        map.forEach(multiValueMap::add);
        return multiValueMap;
    }

    // 添加请求头的工具方法
    private WebClient.RequestHeadersSpec<?> addHeaders(WebClient.RequestHeadersSpec<?> requestSpec, Map<String, String> headers) {
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            requestSpec.header(entry.getKey(), entry.getValue());
        }
        return requestSpec;
    }
}
